package logger;

import java.io.*;
import java.nio.*;
import java.text.SimpleDateFormat;

/**
 *
 * @author BDSHADOW
 */
public class Logger {
    private String logfile = "log.txt";    
    
    private int next = 1;
    private String pattern = "%m\n";
    private int filesize = 10485760; // 10Mb
    
    private int level = LogLevel.TRACE;
    private CharBuffer buffer;
    private PrintWriter writer;
    private File file;
    private ConcurentFileWriter conc_writer;
    
    private SimpleDateFormat time;
    boolean append;
    
    public Logger() {
        CharBuffer buffer = CharBuffer.allocate(131072); // 128 Kb
        this.buffer = buffer;
        time = new SimpleDateFormat("MM.dd kk:mm:ss SSSS");
    }

    public void addFileAppender(String filepath, boolean append, int size) throws IOException {
        this.logfile = filepath;
        this.file = new File(filepath);
        this.filesize = size;
        this.append = append;
        this.writer  = new PrintWriter(new FileWriter(filepath, append));
        this.conc_writer = new ConcurentFileWriter(file, this.writer, append);
    }
    
    public void setLevel(int level) {
        this.level = level;
    }
    
    public void setLogFileSize(int size) {
        this.filesize = size;
    }
    
    public void setPattern(String pattern) {
        this.pattern = pattern;
    }
    
    public void trace(String message) throws FileNotFoundException, IOException {
        if (level >= LogLevel.TRACE) {
            logWriter(message, LogLevel.TRACE);
        }
    }
    public void debug(String message) throws FileNotFoundException, IOException {
        if (level >= LogLevel.DEBUG) {
            logWriter(message, LogLevel.DEBUG);
        }
    }
    public void info(String message) throws FileNotFoundException, IOException {
        if (level >= LogLevel.INFO) {
            logWriter(message, LogLevel.INFO);
        }
    }
    public void warn(String message) throws FileNotFoundException, IOException {
        if (level >= LogLevel.WARN) {
            logWriter(message, LogLevel.WARN);
        }
    }
    public void error(String message) throws FileNotFoundException, IOException {
        if (level >= LogLevel.ERROR) {
            logWriter(message, LogLevel.ERROR);
        }
    }
    public void fatal(String message) throws FileNotFoundException, IOException {
        if (level >= LogLevel.FATAL) {
            logWriter(message, LogLevel.FATAL);
        }
    }
    
    private void logWriter(String message, int level) throws FileNotFoundException, IOException {
        String patterned = getPatterned(message, level);
        if (patterned.length() + 2 > buffer.remaining()) {
            if (patterned.length() + 2 > filesize - file.length()) {
                newLogFile();
            }
            unloadBuffer();
            buffer.put(patterned);
        } else {
            buffer.put(patterned);
            buffer.put("\r\n");
        }
    }
    
    public void stop() throws FileNotFoundException, IOException {
        if (buffer.position() + 2 > filesize - file.length()) {
                newLogFile();
            }
        unloadBuffer();
        writer.close();
    }
    
    private void unloadBuffer() throws IOException {            //подсушили код
        buffer.flip();
        conc_writer.write(buffer);
        buffer.clear();
    }
    
    private void newLogFile() throws FileNotFoundException, IOException {
        logfile = String.valueOf(next) + "_" + logfile;
        file = new File(logfile);
        next++;
        writer.close();
        writer = new PrintWriter(file);
        conc_writer = new ConcurentFileWriter(file, writer);
    }
    
    private String getPatterned(String mes, int level) {
        String pattern = this.pattern;
        pattern = pattern.replace("%m", mes);
        pattern = pattern.replace("%t", time.format(System.currentTimeMillis()));
        pattern = pattern.replace("%l", LogLevel.level.get(level));
        return pattern;
    }
}